package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.heima.common.exception.CustomException;
import com.heima.feign.client.ArticleFetignClient;
import com.heima.model.article.dto.ArticleDto;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.NewsDto;
import com.heima.model.wemedia.dtos.WmNewsDownOrUpDto;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.entity.*;
import com.heima.model.wemedia.vo.WmNewsVo;
import com.heima.utils.common.threadUtil.ThreadLocalUtil;
import com.heima.model.constants.KafkaMessageConstants;
import com.heima.wemedia.mapper.*;
import com.heima.wemedia.service.WmNewsService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 自媒体文章表(WmNews)表服务实现类
 *
 * @author makejava
 * @since 2023-06-14 09:36:40
 */
@Service("wmNewsService")
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Resource
    private WmNewsMapper wmNewsMapper;

    @Resource
    private WmMaterialMapper wmMaterialMapper;

    @Resource
    private WmNewsMaterialMapper wmNewsMaterialMapper;

    @Resource
    private ArticleFetignClient articleFetignClient;

    @Resource
    private KafkaTemplate kafkaTemplate;

    @Resource
    private WmUserMapper wmUserMapper;

    @Resource
    private WmChannelMapper wmChannelMapper;

    @Override
    public ResponseResult submitNews(WmNewsDto dto) {

        //1.校验请求参数,判断参数是否为空，以及文章标题是否为空
        if(dto==null||StringUtils.isEmpty(dto.getTitle())){
            //返回错误信息
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //判断文章标题是否超出长度30
        if(dto.getTitle().length()>30){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //获取封面图片信息
        List<String> coverImages = dto.getImages();
        //获取内容图片信息
        String content = dto.getContent();
        List<String> contextImages = extractContentImage(content);
        //判断文章封面设置是否为自动 0:无封面 1:单图 3:多图
        Short type=dto.getType();
        if(type==-1){
            if(contextImages.size()>=3){
                coverImages=contextImages.stream().limit(3).collect(Collectors.toList());
                type=3;
            }else if(contextImages.size()>0){
                coverImages=contextImages.stream().limit(1).collect(Collectors.toList());
                type=1;
            }else{
                coverImages= Collections.emptyList();
                type=0;
            }
        }

        //封装数据保存文章数据到文章表
        WmNews wmNews = saveWmNews(dto, coverImages,type);

        //封装数据保存到文章素材的关联表


        saveWmNewsMatrialRelation(wmNews.getId(),coverImages,contextImages);
        //发送审核消息
        //发送消息通知审核服务进行文章审核，1：提交 (待审核) 才需要审核
        if(wmNews.getStatus()==1){
            kafkaTemplate.send(KafkaMessageConstants.WM_NEWS_AUTO_SCAN_TOPIC,wmNews.getId().toString());
        }
        return ResponseResult.okResult("文章发布成功");

    }

    /**
     * 分页查询文章列表
     * @param wmNewsPageReqDto
     * @return
     */
    @Override
    public ResponseResult pageList(WmNewsPageReqDto wmNewsPageReqDto) {
        Page<WmNews> wmNewsPage = new Page<>(wmNewsPageReqDto.getPage(),wmNewsPageReqDto.getSize());
        LambdaQueryWrapper<WmNews> wrapper = Wrappers.<WmNews>lambdaQuery();
        //文章状态查询
        if(wmNewsPageReqDto.getStatus()!=null){
            wrapper.eq(WmNews::getStatus,wmNewsPageReqDto.getStatus());
        }
        //频道
        if(wmNewsPageReqDto.getChannelId()!=null){
            wrapper.eq(WmNews::getChannelId,wmNewsPageReqDto.getChannelId());
        }
        //关键字
        if(!StringUtils.isEmpty(wmNewsPageReqDto.getKeyword())){
            wrapper.like(WmNews::getTitle,wmNewsPageReqDto.getKeyword());
        }
        //时间
        if(wmNewsPageReqDto.getBeginPubdate()!=null&&wmNewsPageReqDto.getEndPubdate()!=null){
            wrapper.between(WmNews::getPublishTime,wmNewsPageReqDto.getBeginPubdate(),wmNewsPageReqDto.getEndPubdate());
        }
        //用户id
        wrapper.eq(WmNews::getUserId,ThreadLocalUtil.get().getId());

        Page<WmNews> page = wmNewsMapper.selectPage(wmNewsPage, wrapper);
        PageResponseResult result = new PageResponseResult((int)page.getPages(), (int)page.getSize(), (int)page.getTotal());
        result.setData(page.getRecords());
        return result;

    }

    @Override
    public ResponseResult editNews(Long id) {

        WmNews wmNews = wmNewsMapper.selectById(id);
        if(wmNews==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        return ResponseResult.okResult(wmNews);
    }

    /**
     * 删除文章
     * @param id
     * @return
     */
    @Override
    @Transactional
    public ResponseResult deleteNews(Long id) {
        WmNews wmNews = wmNewsMapper.selectById(id);
        if(wmNews==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"文章不存在");
        }
        if(wmNews.getStatus()==9){
            return ResponseResult.errorResult(AppHttpCodeEnum.NO_OPERATOR_AUTH,"已发布文章不能删除");
        }
        //删除文章列表数据
        wmNewsMapper.deleteById(id);

        LambdaQueryWrapper<WmNewsMaterial> wrapper = Wrappers.<WmNewsMaterial>lambdaQuery();
        wrapper.eq(WmNewsMaterial::getNewsId,id);
        wmNewsMaterialMapper.delete(wrapper);

        return ResponseResult.okResult("删除文章成功");
    }

    /**
     * 上下架文章
     * @param dto
     * @return
     */
    @Override
    public ResponseResult upOrDowmNews(WmNewsDownOrUpDto dto) {

        //1. 查询文章详情
        if (dto == null || dto.getEnable() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        WmNews wmNews = wmNewsMapper.selectById(dto.getId());
        if (wmNews == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //2. 文章状态校验
        if (wmNews.getStatus() != 9) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "未发布文章不能上下架");
        }

        //3. 校验文章配置信息
        if (dto.getEnable() != 0 && dto.getEnable() != 1) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        wmNews.setEnable(dto.getEnable().intValue());
        wmNewsMapper.updateById(wmNews);

        //4. 向kafka发送消息  文章id , 状态-------------------------
        Map<String, String> data = new HashMap<>();
        data.put("newsId", wmNews.getId() + "");
        data.put("enable", dto.getEnable() + "");

        kafkaTemplate.send(KafkaMessageConstants.WM_NEWS_UP_OR_DOWN_TOPIC, JSON.toJSONString(data));

        return ResponseResult.okResult("文章上下架成功");
    }

    /**
     * 管理端文章列表查询
     * @param dto
     * @return
     */
    @Override
    public ResponseResult apNewsList(NewsDto dto) {

        //参数校验
        if(dto==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        LambdaQueryWrapper<WmNews> wrapper = new LambdaQueryWrapper<>();
        if(StringUtils.isNotEmpty(dto.getTitle())){
            wrapper.like(WmNews::getTitle,dto.getTitle());
        }
        if(dto.getStatus()!=null){
            wrapper.eq(WmNews::getStatus,dto.getStatus());
        }

        if(StringUtils.isNotEmpty(dto.getMsg())){
            wrapper.like(WmNews::getContent,dto.getMsg());
        }


        PageHelper.startPage(dto.getPage(),dto.getSize());


        com.github.pagehelper.Page<WmNewsVo > p=wmNewsMapper.selectByPage(dto);

        ResponseResult result=new PageResponseResult(dto.getPage(),dto.getSize(),(int)p.getTotal());

        result.setData(p.getResult());
        return result;


//        Page<WmNews> page = wmNewsMapper.selectPage(new Page<WmNews>(dto.getPage(), dto.getSize()), wrapper);
//        ResponseResult result=new PageResponseResult(dto.getPage(),dto.getSize(),(int)page.getTotal());
//        result.setData(page.getRecords());
    }

    @Override
    public ResponseResult findById(Integer id) {

        if(id==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        WmNewsVo wmNewsVo=wmNewsMapper.getById(id);
        if(wmNewsVo==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        return ResponseResult.okResult(wmNewsVo);
    }

    @Override
    public ResponseResult audit(NewsDto dto) {

        //参数校验
        if(dto==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        if(dto.getId()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        WmNews wmNews = wmNewsMapper.selectById(dto.getId());
        if(wmNews==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        if(StringUtils.isNotEmpty(dto.getMsg())){
            //审核不通过
            wmNews.setReason(dto.getMsg());
            wmNews.setStatus(2);
        }else{
            //审核通过
            wmNews.setStatus(4);

            saveArticle(wmNews);
        }

        wmNewsMapper.updateById(wmNews);

        return ResponseResult.errorResult(AppHttpCodeEnum.SUCCESS);
    }


    /**
     * 保存文章
     * @param wmNews
     */
    private void saveArticle(WmNews wmNews){
        ArticleDto articleDto = new ArticleDto();
        BeanUtils.copyProperties(wmNews,articleDto,"id");
        articleDto.setNewsId(wmNews.getId());

        //封装作者信息
        articleDto.setAuthorId(wmNews.getUserId());
        WmUser wmUser = wmUserMapper.selectById(wmNews.getUserId());
        if(wmUser!=null){
            articleDto.setAuthorName(wmUser.getNickname());
        }
        //封装频道信息
        WmChannel wmChannel = wmChannelMapper.selectById(wmNews.getChannelId());
        if(wmChannel!=null){
            articleDto.setChannelName(wmChannel.getName());
        }
        articleDto.setLayout(wmNews.getType());
        ResponseResult<String> result = articleFetignClient.saveArticle(articleDto);
        if(result.getCode()!=200){
            throw new CustomException(AppHttpCodeEnum.SERVER_ERROR);
        }
    }



    private void saveWmNewsImagesRelation(Long newsId,List<String> images,int type) {
        //对图片URL进行去重
        images = images.stream().distinct().collect(Collectors.toList());
        List<WmMaterial> materialList = wmMaterialMapper.selectList(Wrappers.<WmMaterial>lambdaQuery().in(WmMaterial::getUrl, images));
        //判断是否存在素材缺失
        if(images.size()!=materialList.size()){
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //批量保存素材关系数据到数据库
        List<WmNewsMaterial> wmNewsMaterialList = materialList.stream().map(s -> {
            WmNewsMaterial wmNewsMaterial = new WmNewsMaterial();
            wmNewsMaterial.setNewsId(newsId);
            wmNewsMaterial.setMaterialId(wmNewsMaterial.getNewsId());
            wmNewsMaterial.setType(type);
            return wmNewsMaterial;
        }).collect(Collectors.toList());

        //保存到新闻素材关系表
        wmNewsMaterialMapper.saveNewsMaterialRelation(wmNewsMaterialList);

    }


    /**
     * 保存自媒体文章封面以及自媒体文章内容图片和素材的引用关系
     * @param id
     * @param coverImages
     * @param contentImage
     */
    private void saveWmNewsMatrialRelation(Long id,List<String> coverImages,List<String> contentImage){

        //1.保存自媒体封面的素材应用
        if(!CollectionUtils.isEmpty(coverImages)){
            saveWmNewsImagesRelation(id,coverImages,0);
        }
        //保存自媒体内容素材引用
        if(!CollectionUtils.isEmpty(contentImage)){
            saveWmNewsImagesRelation(id,contentImage,1);
        }
    }

    /**
     * 抽取文章中的图片数据
     * @param content
     * @return
     */
    private List<String> extractContentImage(String content) {
        //判断文章内容content是否为空
        if(StringUtils.isEmpty(content)){
            return Collections.emptyList();
        }

        List<Map> mapList = JSON.parseArray(content, Map.class);
        List<String> list = mapList.stream().filter(s -> "image".equals(s.get("value")))
                .map(s -> s.get("value").toString())
                .collect(Collectors.toList());
        return list;
    }

    /**保存文章数据
     *
     * @param dto
     * @param coverImages
     * @return
     */
    private WmNews saveWmNews(WmNewsDto dto, List<String> coverImages,short type) {
        WmNews wmNews = new WmNews();
        BeanUtils.copyProperties(dto,wmNews,"id");
        //封装图片
        wmNews.setImages(StringUtils.join(coverImages,","));
        //封装用户id
        wmNews.setUserId(ThreadLocalUtil.get().getId().longValue());
        //封装类型
        wmNews.setType((int)type);
        //封装状态
        wmNews.setStatus(dto.getStatus().intValue());
        wmNews.setEnable(1);
        //id为空，代表新增
        if(dto.getId()==null) {
            wmNewsMapper.insert(wmNews);
            return wmNews;
        }

        //文章id不为空，代表修改
        wmNews.setId(dto.getId());
        wmNewsMapper.updateById(wmNews);
        //删除旧文章和素材的关联数据
        wmNewsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getNewsId,wmNews.getId()));
        return wmNews;
    }
}

